#ifndef CH_EDITECTRL_H
#define CH_EDITECTRL_H

#pragma once

#include <afxole.h>
#include <afxtempl.h>

#pragma warning (disable : 4100) 

#define ID_EDITCTRL 1
#define CH_EDIT_SETCARET	1245

// UAT - undo action type
#define UAT_TYPE		0x000000FF
#define UAT_REASON		0xFFFFFF00

static const DWORD g_dwUATUndefined		= 0;
static const DWORD g_dwUATInsertData	= 0x01;
static const DWORD g_dwUATDeleteData	= 0x02;
static const DWORD g_dwUATIndentData	= 0x04;

static const DWORD g_dwUATTyping		= 0x100;
static const DWORD g_dwUATCut			= 0x200;
static const DWORD g_dwUATPaste			= 0x400;
static const DWORD g_dwUATDelete		= 0x800;
static const DWORD g_dwUATBackspace		= 0x1000;
static const DWORD g_dwUATDragDrop		= 0x2000;
static const DWORD g_dwUATEnter			= 0x4000;
static const DWORD g_dwUATIndent		= 0x8000;
static const DWORD g_dwUATUnindent		= 0x10000;
static const DWORD g_dwUATTab			= 0x20000;


static const DWORD g_dwUAFIns			= 0x1;
static const DWORD g_dwUAFOvr			= 0x2;

// canceled operations
static const DWORD g_dwOpUndo			= 0x1;
static const DWORD g_dwOpRedo			= 0x2;
static const DWORD g_dwOpSetOvrMode		= 0x4;
static const DWORD g_dwOpInvokeIS		= 0x8;
static const DWORD g_dwOpLeft			= 0x10;
static const DWORD g_dwOpRight			= 0x20;
static const DWORD g_dwOpUp				= 0x40;
static const DWORD g_dwOpDown			= 0x80;
static const DWORD g_dwOpPgUp			= 0x100;
static const DWORD g_dwOpPgDn			= 0x200;
static const DWORD g_dwOpHome			= 0x400;
static const DWORD g_dwOpNextWord		= 0x800;
static const DWORD g_dwOpPrevWord		= 0x1000;
static const DWORD g_dwOpPrevIndent		= 0x2000;
static const DWORD g_dwOpInsTab			= 0x4000;
static const DWORD g_dwOpLineConcat		= 0x8000;
static const DWORD g_dwOpDelete			= 0x10000;
static const DWORD g_dwOpPaste			= 0x20000;
static const DWORD g_dwOpCopy			= 0x40000;
static const DWORD g_dwOpCut			= 0x80000;
static const DWORD g_dwOpDelSelText		= 0x100000;
static const DWORD g_dwOpMakeSel		= 0x200000;
static const DWORD g_dwOpIndent			= 0x400000;
static const DWORD g_dwOpDragDrop		= 0x800000;
static const DWORD g_dwOpLineBroken		= 0x1000000;	

// canceled operation reasons
static const DWORD g_dwOpReasonLength	= 0x10000000;
static const DWORD g_dwOpReasonBufEmpty	= 0x20000000;	
static const DWORD g_dwOpReasonReadOnly	= 0x40000000;	
static const DWORD g_dwOpReasonError	= 0x80000000;	


static const DWORD g_dwCHEdit_BookMark			= 0x1;
static const DWORD g_dwCHEdit_NamedBookMark		= 0x2;
static const DWORD g_dwCHEdit_LineColorMarker	= 0x4;
static const DWORD g_dwCHEdit_MarkerReserved	= 0x0000FFF0;
static const DWORD g_dwCHEdit_FirstUserDefinedMarker = 0x00010000;

/////////////////////////////////////////////////////////////////////////////
// CHEditCtrl window

struct CH_BASE_UNDO_DATA
{
	virtual ~CH_BASE_UNDO_DATA () {}
};

struct  CH_EDIT_UNDO_ACTION
{
	CH_EDIT_UNDO_ACTION ()
	{
		m_nActionOffset = -1;
		m_nCursorOffset = -1;
		m_dwActionType = g_dwUATUndefined;
		m_dwFlags = g_dwUAFIns;
		m_lpActionData = NULL;
		m_bDestroyActionData = FALSE;
		m_bForceNextUndo = FALSE;
	}

	~CH_EDIT_UNDO_ACTION ()
	{
		if (m_bDestroyActionData)
		{
			delete m_lpActionData;
		}
	}

	int						m_nActionOffset;
	int						m_nCursorOffset;
	DWORD					m_dwActionType;
	CString					m_strActionText;
	CH_BASE_UNDO_DATA*		m_lpActionData;
	DWORD					m_dwFlags;
	BOOL					m_bForceNextUndo;

	BOOL					m_bDestroyActionData;
};

struct CH_EDIT_UNDO_INDENT_DATA : public CH_BASE_UNDO_DATA
{
	CH_EDIT_UNDO_INDENT_DATA () : m_nStartOffset (0), m_nEndOffset (0), m_bForward (FALSE)
	{
	}
	CH_EDIT_UNDO_INDENT_DATA (int nStart, int nEnd, int bFwd) :
					m_nStartOffset (nStart), m_nEndOffset (nEnd), m_bForward (bFwd)
	{
	}

	int				m_nStartOffset;
	int				m_nEndOffset;
	BOOL			m_bForward;
	CStringArray	m_arInsDelStrings;
};

struct CH_EDIT_COLOR_BLOCK  
{
	CH_EDIT_COLOR_BLOCK () :  m_clrForeground ((COLORREF)-1), 
								m_clrBackground ((COLORREF)-1), 
								m_bWholeText (FALSE), m_bAllowNestedBlocks (FALSE)
	{
	}

	CString		m_strOpen;
	CString		m_strClose;
	COLORREF	m_clrForeground;
	COLORREF	m_clrBackground;

	BOOL		m_bWholeText;
	BOOL		m_bAllowNestedBlocks;

	virtual bool operator==(CH_EDIT_COLOR_BLOCK& srcBlock)
	{
		return (m_bWholeText == srcBlock.m_bWholeText && 
				m_strOpen == srcBlock.m_strOpen && 
				m_strClose == srcBlock.m_strClose);
	}
};

struct CH_EDIT_SYNTAX_COLOR
{
	CH_EDIT_SYNTAX_COLOR () : m_clrForeground ((COLORREF)-1), 
								m_clrBackground ((COLORREF)-1),
								m_bCaseSensitive (TRUE)
	{
	}						

	CH_EDIT_SYNTAX_COLOR (COLORREF clrFore, COLORREF clrBk, BOOL bCaseSensitive = TRUE) : 
				m_clrForeground (clrFore), m_clrBackground (clrBk), 
				m_bCaseSensitive (bCaseSensitive)
	{
	}

	COLORREF	m_clrForeground;
	COLORREF	m_clrBackground;
	BOOL		m_bCaseSensitive;
};

struct CH_EDIT_COLOR_AREA 
{
	int			m_nStart;
	int			m_nEnd;
	COLORREF	m_clrForeground;
	COLORREF	m_clrBackground;

	CH_EDIT_COLOR_AREA& operator= (CH_EDIT_COLOR_BLOCK& srcBlock)
	{
		m_clrForeground = srcBlock.m_clrForeground;
		m_clrBackground = srcBlock.m_clrBackground;

		return *this;
	}
};


enum CHEditMarkerRange
{
	NOT_IN_RANGE,
	FULL_IN_RANGE,
	PARTIAL_IN_RANGE
};

class CHEditMarker : public CObject
{
	DECLARE_DYNAMIC(CHEditMarker)
public:
	CHEditMarker () : m_nLine (-1), m_pData (NULL), m_dwMarkerType ((DWORD) -1)
	{

	}

	CHEditMarker (const CHEditMarker& srcMarker)
	{
		Copy (srcMarker);
	}

	~CHEditMarker ()
	{
		DestroyData ();
	}

	virtual CHEditMarker& operator=(const CHEditMarker& srcMarker)
	{
		Copy (srcMarker);
		return *this;
	}

	virtual void Copy (const CHEditMarker& srcMarker)
	{
		m_nLine = srcMarker.m_nLine;
		m_dwMarkerType = srcMarker.m_dwMarkerType;
		CopyData ((DWORD) srcMarker.m_pData);
	}

	virtual CHEditMarkerRange IsInRange (int nStartPos, int nEndPos) const
	{
		if (m_nLine >= nStartPos && m_nLine <= nEndPos)
		{
			return FULL_IN_RANGE;
		}

		return NOT_IN_RANGE;
	}

	virtual void UpdateMarkerForDeletedRange (int /*nStartPos*/, int /*nEndPos*/) {}
	virtual bool CompareData (DWORD dwData) const
	{
		return ((DWORD) m_pData) == dwData;
	}

	virtual void CopyData (DWORD dwData) {}
	virtual void DestroyData () {}

	virtual void Serialize (CArchive& ar)
	{
		CObject::Serialize (ar);
		if (ar.IsLoading ())
		{
			ar >> m_nLine;
			ar >> m_dwMarkerType;
		}
		else
		{
			ar << m_nLine;
			ar << m_dwMarkerType;
		}

		SerializeData (ar);
	}

	virtual void SerializeData (CArchive& ar)
	{
		if (ar.IsLoading ())
		{
			ar << (DWORD) m_pData;
		}
		else
		{
			DWORD dw = 0;
			ar >> dw;
			m_pData = (LPVOID) dw;
		}
	}

public:	
	int			m_nLine;
	DWORD		m_dwMarkerType;
	LPVOID		m_pData;
};

class CHLineColorMarker : public CHEditMarker
{
	DECLARE_DYNAMIC(CHLineColorMarker)

public:	
	CHLineColorMarker () : m_clrForeground ((COLORREF)-1), 
							  m_clrBackground ((COLORREF)-1),
							  m_nLineCount (0), m_bFullLine (FALSE)
	{
		m_dwMarkerType = g_dwCHEdit_LineColorMarker;
	}							  

	CHLineColorMarker (const CHLineColorMarker& srcMarker)
	{
		Copy (srcMarker);
	}

	virtual void Copy (const CHLineColorMarker& srcMarker)
	{
		CHEditMarker::Copy (srcMarker);
		m_clrForeground = srcMarker.m_clrForeground;
		m_clrBackground = srcMarker.m_clrBackground;
		m_nLineCount	= srcMarker.m_nLineCount;
		m_bFullLine		= srcMarker.m_bFullLine;
	}

	virtual CHEditMarkerRange IsInRange (int nStartPos, int nEndPos) const
	{
		int nEndLine = m_nLine + m_nLineCount;
		if (m_nLine > nEndPos || nEndLine < nStartPos)
		{
			return NOT_IN_RANGE;
		}

		if (m_nLine >= nStartPos && m_nLine <= nEndPos &&
			nEndLine <= nEndPos)
		{
			return FULL_IN_RANGE;
		}

		return PARTIAL_IN_RANGE;
	}

	virtual void UpdateMarkerForDeletedRange (int nStartPos, int nEndPos)
	{
		int nEndLine = m_nLine + m_nLineCount;

		if (m_nLine > nEndPos || nEndLine < nStartPos)
		{
			return;
		}

		if (m_nLine >= nStartPos && m_nLine <= nEndPos &&
			nEndLine <= nEndPos)
		{
			// the whole marker in the deleted range - nothing to update
			return;
		}
		
		if (m_nLine < nStartPos && nEndLine <= nEndPos)
		{
			// bottom of marker is deleted
			m_nLineCount -= nEndLine - nStartPos + 1;
		}
		else if (m_nLine >= nStartPos && nEndLine > nEndPos)
		{
			// top of marker is deleted
			m_nLineCount -= nEndPos - m_nLine + 1;
			m_nLine = nStartPos;
		}
		else if (m_nLine < nStartPos && nEndLine > nEndPos)
		{
			// middle of the marker is deleted
			m_nLineCount -= nEndPos - nStartPos + 1;
		}
	}

	virtual void Serialize (CArchive& ar)
	{
		CHEditMarker::Serialize (ar);
		if (ar.IsLoading ())
		{
		}
		else
		{
		}
	}

	COLORREF	m_clrForeground;
	COLORREF	m_clrBackground;
	int			m_nLineCount;

	BOOL		m_bFullLine;
};


//class CHIntelliSenseWnd;
class CHEditCtrl;

class CHEditCtrlDropTarget : public COleDropTarget
{
public:
	CHEditCtrlDropTarget()
	{
		m_pOwner = NULL;
	}

// Attributes
protected:
	CHEditCtrl* m_pOwner;

// Operations
public:
	BOOL Register (CHEditCtrl* pOwner);

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CHTabDropTarget)
	public:
	virtual DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
	virtual void OnDragLeave(CWnd* pWnd);
	virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
	virtual DROPEFFECT OnDropEx(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, DROPEFFECT dropList, CPoint point);
	//}}AFX_VIRTUAL
};

/*
class CHIntelliSenseData : public CObject
{
public:
	CString		m_strItemName;
	CString		m_strItemHelp;
	int			m_nImageListIndex;
	DWORD		m_dwData;
};
*/

class CHEditCtrl : public CWnd
{
//	friend class CHIntelliSenseWnd;
//	friend class CHIntelliSenseLB;

	DECLARE_DYNAMIC(CHEditCtrl)
protected:
	COLORREF PixelAlpha (COLORREF srcPixel, int percent);
	COLORREF HLStoRGB_ONE( double H, double L, double S );
	void RGBtoHSL( COLORREF rgb, double *H, double *S, double *L );
	double HuetoRGB(double m1, double m2, double h );

// Construction
public:
	CHEditCtrl();

// Attributes
public:
	CToolTipCtrl m_wndToolTip;

	CString		m_strWordDelimeters;
	CString		m_strSpecialDelimiters;
	CString		m_strNonSelectableChars;
//	CString		m_strIntelliSenseChars;
	CString		m_strIndentChars;

	CString		m_strContinueStringSymbols;

	COLORREF	m_clrBack;
	COLORREF	m_clrText;

	COLORREF	m_clrBackSelActive;
	COLORREF	m_clrBackSelInActive;
	COLORREF	m_clrTextSelActive;
	COLORREF	m_clrTextSelInActive;

	BOOL		m_bReplaceTabsAndEOLOnCopy;

	int			m_nLineVertSpacing;
	int			m_nLeftMarginWidth;
	int			m_nIndentSize;
	int			m_nTabSize;

	int			m_nScrollRightOffset; // for how many symbols to scroll the text when scrolling
									  // right - in percents from the window width
	int			m_nScrollLeftOffset;  // for how many symbols to scroll the text when scrolling
									  // left
	UINT		m_nScrollTimeOut;

	BOOL		m_bEnableWholeTextCopy;	// Allow to copy the whole buffer to clipboard

	int GetCurRow () const
	{
		return RowFromOffset (m_nCurrOffset); //m_nCurRow;
	}

	int GetCurRowX() const
	{
		return m_nCurRow;
	}

	int GetCurColumn () const
	{
		return m_nCurColumn;
	}

	int GetLineHeight () const
	{
		return m_nLineHeight;
	}

	int GetCurOffset () const
	{
		return m_nCurrOffset;
	}

	 void SetReadOnly (BOOL bReadOnly = TRUE)
	 {
		 m_bReadOnly = bReadOnly;
	 }

	 BOOL IsReadOnly () const
	 {
		 return m_bReadOnly;
	 }

	int GetLineCount () const
	{
		return m_nTotalLines;
	}

protected:
	CString		m_strBuffer;
	BOOL		m_bIsModified;

	int			m_nMaxScrollWidth;
	
	BOOL		m_bReadOnly;

	int			m_nLastKey;
	int			m_nPrevKey;

	HFONT		m_hFont;
	int			m_nLineHeight;
	int			m_nMaxCharWidth;
	int			m_nAveCharWidth;

	CRect		m_rectText;

	int			m_nCurrOffset;
	CPoint		m_ptCaret;

	int			m_iStartSel;
	int			m_iEndSel;

	CPoint		m_ptStartBlockSel;
	CPoint		m_ptEndBlockSel;

	BOOL		m_bAltPressedForBlockSel;

	BOOL		m_bBlockSelectionMode;

	int			m_nScrollOffsetHorz;
	int			m_nScrollOffsetVert;

	int			m_nTopVisibleOffset;
	int			m_nTotalLines;

	CSize		m_szTotalScroll;

	int			m_nCurRow;
	int			m_nCurColumn;

	int			m_nSavedOffset;
	int			m_nDropOffset;
	CPoint		m_ptSavedBlockCaretOffset;

	int			m_nLastSelOffset; // to prevent flashing on MouseMove + sel
	int			m_nLastMaxColumn;

	BOOL		m_bDragTextMode;

	int			m_nScrollTimer;

	int			m_nTabLogicalSize; // size of the tab in logical units
	BOOL		m_bKeepTabs;

	BOOL		m_bEnableToolTips;
	CString		m_strLastDisplayedToolTip;
	BOOL		m_bToolTipCleared;

	COLORREF	m_clrOpenBlockFore;
	COLORREF	m_clrOpenBlockBk;
	int			m_nOpenBlockOffset;

//	CHIntelliSenseWnd*	m_pIntelliSenseWnd;
//	CImageList*				m_pIntelliSenseImgList;
//	CFont*					m_pIntelliSenseLBFont;
//	BOOL					m_bIntelliSenseMode;

	CMap<TCHAR, TCHAR&, int, int> m_mapCharWidth;
	CMap<WORD, WORD&, int, int> m_mapWordWidth;	// thinkry@2003-11-14

	CHEditCtrlDropTarget	m_DropTarget;

	CList <CH_EDIT_UNDO_ACTION*, CH_EDIT_UNDO_ACTION*>	m_lstUndoActions;
	int			m_nUndoBufferSize;
	POSITION	m_posUndoBuffer;
	POSITION	m_posDocSavedUndoPos;
	DWORD		m_dwLastUndoReason;

	BOOL		m_bUndoCharMode; // TRUE - save single chars in each node, FALSE - save words
	BOOL		m_bEOL;
	BOOL		m_bBOL;
	BOOL		m_bIsLastActionUndo;
	BOOL		m_bLeftSelect;	// thinkry@2003-11-14

	// syntax coloring
	CMap  <CString, LPCTSTR, CH_EDIT_SYNTAX_COLOR, CH_EDIT_SYNTAX_COLOR&>	m_mapWordColors;
	CList <CH_EDIT_COLOR_BLOCK, CH_EDIT_COLOR_BLOCK&>						m_lstColorBlocks;

	// markers
	CObList		m_lstMarkers;

	// print
	HFONT		m_hPrinterFont;	// if NULL, mirror display font
	HFONT		m_hMirrorFont;	// font object used when mirroring

private:
	TCHAR m_nLChar;
//	BOOL		m_bIntelliSenseSupport;
	static BOOL	m_bOvrMode; // overwrite mode
	
// Operations
public:

	// File operations:
	BOOL OpenFile (const CString& strFileName);
	BOOL OpenFile (CFile& file);

	BOOL SaveFile (const CString& strFileName);
	BOOL SaveFile (CFile& file);

	virtual BOOL IsModified () const
	{
		return m_bIsModified && 
				(m_posUndoBuffer != NULL && 
				 m_posUndoBuffer != m_posDocSavedUndoPos || 
				 m_posUndoBuffer == NULL && m_bEOL);
	}

	// Scrolling methods:
	BOOL ScrollText (BOOL bDirection);

	BOOL ScrollDown (int fnBar, BOOL bRedrawOnScroll);
	BOOL ScrollUp (int fnBar, BOOL bRedrawOnScroll);

	BOOL ScrollPageDown (int fnBar, BOOL bRedrawOnScroll);
	BOOL ScrollPageUp (int fnBar, BOOL bRedrawOnScroll);

	BOOL ScrollHome (int fnBar, BOOL bRedrawOnScroll);
	BOOL ScrollEnd (int fnBar, BOOL bRedrawOnScroll);

	void UpdateScrollBars ();
	void EnableUndoCharMode (BOOL bEnable = TRUE) {m_bUndoCharMode = bEnable;}

	void FindWordStartFinish (int nCaretOffset, const CString& strBuffer,
		                      int& nStartOffset, int& nEndOffset, BOOL bSkipSpaces = TRUE) const;
	BOOL GetWordFromPoint (CPoint pt, CString& strWord);
	BOOL GetWordFromOffset (int nOffset, CString& strWord);
	
	BOOL OffsetToPoint (int nOffset, CPoint& pt, LPPOINT ptRowColumn = NULL,
					LPINT pnScrollOffset = NULL);
	BOOL DeleteText (int nStartOffset, int nEndOffset, BOOL bRedraw = FALSE);

	BOOL IndentText (int nStartOffset, int nEndOffset, BOOL bForward, 
					BOOL bBlockSelectionMode, BOOL bSelectText, 
					CStringArray& arInsDelText, BOOL bUndoMode);

/*	void SetIntelliSenseImgList (CImageList* pImageList, BOOL bAutoDestroy = FALSE)
	{
		m_pIntelliSenseImgList = pImageList;
	}

	CImageList* GetIntelliSenseImgList () const
	{
		return m_pIntelliSenseImgList;
	}

	void SetIntelliSenseLBFont (CFont* pFont) 
	{
		m_pIntelliSenseLBFont = pFont;
	}

	CFont* GetIntelliSenseLBFont () const
	{
		return m_pIntelliSenseLBFont;
	}

	void SetIntelliSenseWnd (CHIntelliSenseWnd* pWnd)
	{
		m_pIntelliSenseWnd = pWnd;
	}
*/
	int GetNumOfCharsInText (const CString& strText, TCHAR ch);

	int HitTest (CPoint& pt, BOOL bNormalize = FALSE, BOOL bIgnoreTextBounds = FALSE);
	BOOL SetCaret (int nOffset, BOOL bScrollToCaret = TRUE, BOOL bRedrawOnScroll = TRUE);

	const CString& GetText () const 
	{
		return m_strBuffer;
	}

	BOOL GetSelText(CString& strBuffer)
	{
		const int nLen = m_strBuffer.GetLength();
		if(m_iStartSel < 0 || m_iStartSel > nLen ||
			 m_iEndSel < 0 || m_iEndSel > nLen ||
			 m_iStartSel == m_iEndSel)
			return FALSE;

		int iStartSel = min(m_iStartSel, m_iEndSel);
		int iEndSel = max(m_iStartSel, m_iEndSel);
		strBuffer = m_strBuffer.Mid(iStartSel, iEndSel - iStartSel);
		return TRUE;
	}

	TCHAR GetCharAt (int nPos, BOOL bCheckForErros = TRUE) const 
	{
		if (bCheckForErros && (nPos < 0 || nPos >= m_strBuffer.GetLength ()))
		{
			return 0;
		}
		return m_strBuffer.GetAt (nPos);
	}

	BOOL IsInBlock (int nPos, TCHAR chOpen, TCHAR chClose, int& nBlockStart, int& nBlockEnd);

	// Selection methods:
	void GetSel (int& nStartChar, int& nEndChar) const;
	BOOL IsPointInSelectionRect (CPoint pt);
	BOOL DeleteSelectedText (BOOL bRedraw = TRUE, BOOL bCopyToClipboard = FALSE, 
							 BOOL bForceNextUndo = FALSE);

	void ToolTipPop ();

	// Conversion
	void VirtToClient (CPoint& pt);
	void ClientToVirt (CPoint& pt);
	void VirtToClient (CRect& rect);
	void ClientToVirt (CRect& rect);

	// Undo
	virtual void SetLastUndoReason (DWORD dwUndoReason) {m_dwLastUndoReason = dwUndoReason;}
	virtual DWORD GetLastUndoReason () const {return m_dwLastUndoReason;}

	// Print
	void SetPrinterFont(CFont* pFont);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnPrint(CDC* pDC, CPrintInfo* pInfo);

protected:
	void Initialize ();
	void OnChangeFont (CDC* pDC = NULL);
	void InitColors ();
	COLORREF GetDefaultTextColor () const;
	COLORREF GetDefaultBackColor () const;

	int GetCurrRowStart () const;
	int GetCurrRowEnd () const;

	int GetCurrRowTextStart () const;
	int GetRowTextStart (int nRowOffset) const;
	
	int GetRowStart (int nRow) const;
	int GetNumOfColumnsInRowByOffset (int nOffset, int& nRowEndOffset) const;

	int GetOffsetOfColumnInRow (int nColumn, int nRowEndOffset, BOOL bEndOffsetSpecified = TRUE);

	int GetRowStartByOffset (int nOffset) const;
	int GetRowEndByOffset (int nOffset) const;

	int GetColumnFromOffset (int nOffset) const;

	int GetHorzRowExtent (CDC* pDC, int nOffset);


	CFont* SelectFont (CDC* pDC);

	void RedrawRestOfLine (int nOffset);
	void RedrawRestOfText (int nOffset);
	void DrawColorLine (CDC* pDC, int nRow, CRect rectRow);

	BOOL CopyTextToClipboard (LPCTSTR lpszText);
	HGLOBAL CopyTextToClipboardInternal (LPCTSTR lpszText, CLIPFORMAT cFormat);

	BOOL GetSelectionRect (CRect& rect1, CRect& rect2, CRect& rect3);

	void BuildColorAreas (CList <CH_EDIT_COLOR_AREA, CH_EDIT_COLOR_AREA&>& colorAreas,
						  int nStartOffset, int nEndOffset, 
						  CH_EDIT_COLOR_BLOCK* pColorBlockToExclude, 
						  BOOL bRedraw = TRUE);
	BOOL IsOffsetAtColorBlock (int nOffset);

	inline int ReverseFindOneOf (const CString& strBuffer, int nPos, const CString& strChars) const;
	void ReverseFindOneOf(const CString& strCharSet, const int ciStartPos, int& nCurrOffset) const;
	int FindOneOf (const CString& strBuffer, int nPos, const CString& strChars) const;
	int WhileOneOf (const CString& strBuffer, int nOffset, bool bForward, 
		 			const CString& strChars);

	virtual int DrawString (CDC* pDC, LPCTSTR str, CRect rect, int nOrigin, 
							COLORREF clrBack);
	virtual CSize GetStringExtent (CDC* pDC, LPCTSTR str);
	virtual CSize GetStringExtent (CDC* pDC, LPCTSTR lpszString, int nCount);

	BOOL IsInsideSelection (int nOffset, CPoint& ptCharOffset, CRect rectSel, int nCharWidth);
	BOOL IsColoredLine (int nRow, COLORREF& clrFore, COLORREF& clrBack);
	void PrepareBlock (CString& strOut);
	void RetrieveSelectedBlock (CStringArray& arStrings);
	int RowFromOffset (int nOffset, BOOL bCalcAll = FALSE) const;

	void BuildTabString (CString& str);
	void UpdateLineRelatedData (int nStartLine, int nNumLines);
	void RemoveLineDataInRange (int nStartRow, int nEndRow);

	BOOL FindOpenBlock (int nStartOffset, CH_EDIT_COLOR_BLOCK* pFoundBlock);
	int FindCloseBlock (int nStartOffset, CH_EDIT_COLOR_BLOCK* pFoundBlock);

	BOOL IsCharBlockSymbol (TCHAR ch);
	BOOL IsStringHasBlockSymbols (const CString& str);

	BOOL PasteFromDataObject (COleDataObject* pDataObject, 
							  int nInsertFrom = -1, BOOL bRedraw = FALSE, 
							  BOOL bSuppressUndo = FALSE, 
							  BOOL bUpdateLineData = TRUE,
							  BOOL bForceNextUndo = FALSE);

// Overrides
public:
	//---------------------
	// IntelliSense Support
	//---------------------
//	virtual BOOL FillIntelliSenseList (CObList& lstIntelliSenseData, LPCTSTR lpszIntelliSense) const  { return FALSE; }

	virtual BOOL FindText(LPCTSTR lpszFind, BOOL bNext = TRUE, BOOL bCase = TRUE, BOOL bWholeWord = FALSE);
	virtual CSize GetCaretSize () const;
	virtual BOOL OnSetOvrMode ();

	//------------
	// Navigation:
	//------------
	virtual BOOL Left (BOOL bRedrawOnScroll = TRUE);
	virtual BOOL Right (BOOL bMod=FALSE, BOOL bRedrawOnScroll = TRUE);
	virtual BOOL Up (BOOL bSetCaretToMaxColumn = TRUE, BOOL bRedrawOnScroll = TRUE);
	virtual BOOL Down (BOOL bSetCaretToMaxColumn = TRUE, BOOL bRedrawOnScroll = TRUE);
	virtual BOOL Home (BOOL bRedrawOnScroll = TRUE);
	virtual BOOL End (BOOL bRedrawOnScroll = TRUE);
	virtual BOOL StartOfText (BOOL bRedraw = TRUE);
	virtual BOOL EndOfText (BOOL bRedrawOnScroll = TRUE);
	virtual BOOL PageUp (BOOL bRedrawOnScroll = TRUE);
	virtual BOOL PageDown (BOOL bRedrawOnScroll = TRUE);

	virtual BOOL NextWord (BOOL bRedrawOnScroll = TRUE);
	virtual BOOL PrevWord (BOOL bRedrawOnScroll = TRUE);

	virtual BOOL PrevIndent ();

	virtual void OnSetCaret	() 
	{
		NMHDR nm;
		nm.hwndFrom = GetSafeHwnd();
		nm.idFrom  = 0;
		nm.code = CH_EDIT_SETCARET;
		GetParent()->SendMessage(WM_NOTIFY, 0,  (LPARAM)&nm); 
	}
	BOOL HomeX (BOOL bRedrawOnScroll = TRUE);

	virtual BOOL OnScroll (int fnBar, UINT nSBCode, int nPos =-1);

	virtual BOOL SetCaretToLastMaxColumn (int nOffset, BOOL bRedrawOnScroll = TRUE);

	//---------------
	// Insert/delete:
	//---------------
	virtual BOOL InsertChar (TCHAR nChar, BOOL bRedraw = FALSE);
	virtual BOOL InsertText (LPCTSTR lpszText, int nInsertFrom = -1, BOOL bRedraw = FALSE, 
							 BOOL bSuppressUndo = FALSE, BOOL bUpdateLineData = TRUE,
							 BOOL bForceNextUndo = FALSE, BOOL bAlwaysAtEnd = TRUE);
	virtual BOOL InsertTextAsBlock (LPCTSTR lpszText, int nInsertFrom = -1, BOOL bRedraw = FALSE, 
									BOOL bSuppressUndo = FALSE, BOOL bUpdateLineData = TRUE,
									BOOL bForceNextUndo = FALSE);
	virtual BOOL InsertNewLine (BOOL bRedraw = FALSE, BOOL bForceNextUndo = FALSE, 
								int nOffset = -1, BOOL bSetCaret = TRUE);
	virtual BOOL InsertTab (BOOL bRedraw = FALSE);
	virtual BOOL OnDelete (BOOL bRedraw = FALSE, BOOL bForceNextUndo = FALSE);
	virtual BOOL ProcessTextBeforeInsert (CString& strText);

	virtual BOOL OnInsertNewLine (BOOL bForceNextUndo = FALSE, int nOffset = -1, 
									 BOOL bSetCaret = FALSE);

	virtual void OnDeleteTextFromBuffer (int nStartOffset, int nEndOffset, 
										  LPCTSTR lpcszDeletedText);
	virtual void OnInsertTextToBuffer (int nStartOffset, const CString& strInsertedText, 
										BOOL bUpdateLineData = TRUE);

	//---------------
	// Text changing notifications:
	//---------------
	virtual BOOL OnBeforeTextInserted (CString& strInsertedText, int nOffset) {return TRUE;}
	virtual BOOL OnBeforeTextDeleted (int nOffset, const CString& strDeletedText) {return TRUE;}
	virtual void OnAfterTextChanged (int nOffsetFrom, const CString& strText, BOOL bInserted);

	//----------
	// Undo/Redo
	//----------
	virtual void SetOverrideMode (BOOL bSet = FALSE) {m_bOvrMode = bSet;}
	virtual BOOL GetOverrideMode () const {return FALSE; /* m_bOvrMode; */}
	//----------
	// Undo/Redo
	//----------
	virtual BOOL CanUndo () const;
	virtual BOOL CanRedo () const;

	virtual BOOL OnUndo (BOOL bSetCaret = TRUE, BOOL bRedraw = TRUE);
	virtual BOOL OnRedo (BOOL bSetCaret = TRUE, BOOL bRedraw = TRUE);

	void GetUndoActions(CDWordArray& dwaUAT) const;
	void GetRedoActions(CDWordArray& dwaUAT) const;

	virtual void AddUndoAction (CString& strText, DWORD dwAction, int nCurrOffset, BOOL bForceInsertMode, 
								BOOL bForceNextUndo = FALSE);
	virtual void AddUndoAction (TCHAR ch, DWORD dwAction, int nCurrOffset, BOOL bForceInsertMode);
	virtual void AddUndoAction (CH_BASE_UNDO_DATA* lpActionData, DWORD dwAction, BOOL bDestroyData = TRUE);
	virtual void AddUndoAction (CH_EDIT_UNDO_ACTION* pUndoAction);

	virtual BOOL OnBeforeUndoRedo (CH_EDIT_UNDO_ACTION* /*pUndoAction*/) {return TRUE;}	
	virtual void OnAfterUndoRedo (CH_EDIT_UNDO_ACTION* /*pUndoAction*/) {}	
	
	virtual BOOL OnBeforeAddUndoAction (CH_EDIT_UNDO_ACTION* pUndoAction) {return TRUE;}
	virtual void OnRemoveUndoAction (CH_EDIT_UNDO_ACTION* pUndoAction) {};

	virtual BOOL ProcessUndoRedoAction (CH_EDIT_UNDO_ACTION* pUndoAction, BOOL bUndo, BOOL bSetCaret);

	void EmptyUndoList ();

	//----------
	// Selection
	//----------
	enum CH_EDIT_SEL_TYPE
	{
		ST_PREV_WORD,
		ST_NEXT_WORD,
		ST_PREV_SYMBOL,
		ST_NEXT_SYMBOL,
		ST_PREV_LINE,
		ST_NEXT_LINE,
		ST_PREV_PAGE,
		ST_NEXT_PAGE,
		ST_HOME,
		ST_END,
		ST_START_OF_TEXT,
		ST_END_OF_TEXT,
		ST_ALL_TEXT
	};

	virtual BOOL MakeSelection (enum CHEditCtrl::CH_EDIT_SEL_TYPE selType, BOOL bHide = FALSE);
	virtual BOOL RemoveSelection (BOOL bSetCaretToSelStart = TRUE, 
									BOOL bKeepCurrPos = FALSE, BOOL bRedraw = TRUE);
	virtual BOOL IndentSelection (BOOL bForward);
	virtual void SetSel (int nStartSel, int nEndSel, BOOL bNoScroll = FALSE);

	//----------------
	// Copy/Cut/Paste:
	//----------------
	virtual BOOL Copy ();
	virtual BOOL Cut ();
	virtual BOOL Paste (int iPos = -1);
	virtual BOOL PasteText(const CString& strText, int iPos = -1);
	virtual BOOL Clear ();

	virtual BOOL IsPasteEnabled () const;

	virtual BOOL IsCopyEnabled () const
	{
		return m_bEnableWholeTextCopy || (m_iStartSel >= 0 && m_iEndSel >= 0 &&
											(m_iStartSel != m_iEndSel));
	}

	virtual BOOL IsCutEnabled () const
	{
		return m_iStartSel >= 0 && m_iEndSel >= 0 && (m_iStartSel != m_iEndSel);
	}

	virtual BOOL IsIndentEnabled (BOOL bForward);

	//--------
	// Drawing
	//--------
	virtual void RedrawText (int nStartRow, int nEndRow = 0);
	virtual void RedrawTextOffsets (int nStartOffset, int nEndOffset);

	virtual void OnFillBackground (CDC* pDC);
	virtual void OnDrawText (CDC* pDC);
	virtual void OnDrawSideBar (CDC* pDC, CRect rect);

	virtual void OnDrawMarker (CDC* pDC, CRect rectMarker, const CHEditMarker* pMarker);

	//--------------------
	// Drag & Drop support
	//--------------------
	virtual BOOL OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);
	virtual DROPEFFECT OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);

	virtual void OnDragLeave();
	virtual DROPEFFECT OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);

	//----------------
	// Syntax coloring
	//----------------
	void SetWordColor (CString strWord, 
						COLORREF clrFrgnd = -1, 
						COLORREF clrBkgnd = -1,
						BOOL bCaseSensitive = TRUE);
	BOOL RemoveWordFromColorTable (CString strWord);
	void RemoveAllWordsFromColorTable ();

	POSITION SetBlockColor (CString strBlockOpen, CString strBlockClose, 
							BOOL bWholeText = FALSE, 
							COLORREF clrFrgnd = (COLORREF) -1, 
							COLORREF clrBkgnd = (COLORREF) -1);

	BOOL RemoveBlockColor (POSITION posBlock);
	void RemoveAllBlocks ();

	virtual BOOL OnGetWordColor (const CString& strWord, COLORREF& clrText, COLORREF& clrBk, int nPos);
	virtual void OnGetCharColor (TCHAR ch, int nOffset, COLORREF& clrText, COLORREF& clrBk) {}
	
	//-------------
	// XML settings
	//-------------
	virtual BOOL LoadXMLSettings (const CString& strFileName);
	virtual BOOL LoadXMLSettingsFromBuffer (const CString& strBuffer);
	virtual void RemoveXMLSettings ();

	//---------------------
	// IntelliSense Support
	//---------------------
//	virtual BOOL OnFillIntelliSenseList (int& nCurrOffset, CObList& lstIntelliSenseData) const;
//	virtual BOOL OnBeforeInvokeIntelliSense (const CString& strBuffer, int& nCurrOffset, CString& strIntelliSense) const {return TRUE;}
//	virtual BOOL InvokeIntelliSense (CObList& lstIntelliSenseData, CPoint ptTopLeft);
//	virtual BOOL IntelliSenseCharUpdate(const CString& strBuffer, int nCurrOffset, TCHAR nChar, CString& strIntelliSense) { return FALSE; }

	//---------------------
	// IntelliSense Support
	//---------------------
//	BOOL EnableIntelliSense(BOOL bFl = TRUE);

/*	inline BOOL IsIntelliSenseEnabled() const
	{
		return m_bIntelliSenseSupport;
	}
	
	virtual BOOL InvokeIntelliSense ();
*/
	//---------------
	// Marker Support
	//---------------
	BOOL		ToggleMarker (int nRow, DWORD dwMarkerType, LPVOID lpData = NULL, BOOL bRedraw = TRUE);
	POSITION	SetMarker (CHEditMarker* pMarker, int nRow = -1, BOOL bRedraw = TRUE);
	POSITION	GetMarker (int nRow, CHEditMarker** ppMarker, DWORD dwMarkerType);

	BOOL		SetMarkerData (int nRow, LPVOID lpData, DWORD dwMarkerType, BOOL bRedraw = TRUE);
	void		SetMarkerData (POSITION pos, DWORD dwData);
	POSITION	InsertMarker (CHEditMarker* pMarker, BOOL bRedraw = TRUE);

	void		DeleteMarker (POSITION posMarker);
	BOOL		DeleteMarker (int nRow, DWORD dwMarkerType, BOOL bRedraw = TRUE);
	void		DeleteAllMarkers (DWORD dwMarkerType = (DWORD) -1, BOOL bRedraw = TRUE);
	BOOL		GoToNextMarker (DWORD dwMarkerType, BOOL bDirection = TRUE);

	void		GetMarkerListByType (CObList& lstMarkers, DWORD dwMarkerType) const; 
	void		GetMarkersInRange (int nRowStart, CObList& lstMarkers, 
									DWORD dwMarkerType = (DWORD) -1, int nRowEnd = -1) const;

	virtual CHEditMarker* FindMarkerByData (DWORD dwData) const;
	virtual void GetMarkerListByData (CObList& lstMarkers, DWORD dwData) const;
	
	CHEditMarker* GetMarker (POSITION pos) 
	{
		ASSERT_VALID (this);
		return DYNAMIC_DOWNCAST (CHEditMarker, m_lstMarkers.GetAt (pos));
	}

	const CObList& GetMarkerList () const 
	{
		return m_lstMarkers;
	} 

	virtual BOOL GoToMarker (const CHEditMarker* pMarker);
	
	virtual BOOL HasMarkers (DWORD dwMarkerType = (DWORD) -1);

	void RedrawMarkerArea (int nRow = -1, BOOL bFullLine = FALSE);

	virtual BOOL CanUpdateMarker (CHEditMarker* pMarker) const  {return TRUE;}
	virtual BOOL CanRemoveMarker (CHEditMarker* pMarker) const  {return TRUE;}
	
	virtual BOOL OnUpdateMarkerLine (int nNewLine) {return TRUE;}
	virtual BOOL OnRemoveMarker (CHEditMarker* pMarker, POSITION posMarker) {return TRUE;}

	void CleanUpMarkers ();

	POSITION SetLineColorMarker (int nRow = -1, COLORREF clrFore = (DWORD)-1, 
								 COLORREF clrBk = (DWORD) -1, BOOL bFullLine = TRUE, 
								 int nLineCount = 0, DWORD dwMarkerType = g_dwCHEdit_LineColorMarker);

	//----------------
	// Tooltip Support
	//----------------
	void ShowContextTip();
	virtual BOOL OnGetTipText (CString& strTipString) {return TRUE;}
	void EnableToolTips (BOOL bEnable = TRUE);

	//--------
	// Notifications
	//--------
	virtual void OnFailedOperation (DWORD dwOpType) {}
	
	//--------
	// Options
	//--------
	BOOL	m_bDefaultIndent;

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CHEditCtrl)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
	virtual void Serialize(CArchive& ar);
	protected:
	virtual void PreSubclassWindow();
	//}}AFX_VIRTUAL

// Implementation
public:
	int AdjustUndoTextLength(int nOffset, int nLen);
	int InsertR(int nStart, int& nEnd);
	int RemoveR(int nStart, int& nEnd);
	int FormatRange(int nOffset, int nCount);
	inline int GetParEndByOffset(int nOffset);
	inline int GetParStartByOffset(int nOffset);
	inline int GetRowCountOfPar(int nOffset);
	int AdjustCurrOffset(int nOld, int nNew);

	BOOL SaveX();

	virtual ~CHEditCtrl();

	// Generated message map functions
protected:
	WORD m_wAutoWidth;
	BOOL AdjustOffsetX(int nOffset);

//	BOOL m_bIntelliSenseUpdate;
	//{{AFX_MSG(CHEditCtrl)
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnPaint();
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnKillFocus(CWnd* pNewWnd);
	afx_msg void OnSetFocus(CWnd* pOldWnd);
	afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg void OnSysColorChange();
	//}}AFX_MSG
	afx_msg LRESULT OnSetFont (WPARAM, LPARAM);
	afx_msg LRESULT OnGetFont (WPARAM, LPARAM);
	afx_msg BOOL OnTTNeedTipText(UINT /*id*/, NMHDR* pNMH, LRESULT* /*pResult*/);
	afx_msg LRESULT OnSetText (WPARAM, LPARAM);
	afx_msg LRESULT OnGetText (WPARAM, LPARAM);
	DECLARE_MESSAGE_MAP()
};

//////////////////////////////////////////////////////////////////////////////
// CHEditCtrl notification messages:

extern UINT CHM_ON_EDITCHANGE;

/////////////////////////////////////////////////////////////////////////////


#endif //CH_EDITECTRL_H
